package com.example.shuiyin.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.shuiyin.dto.ApiResponse;
import com.example.shuiyin.dto.FileDto;
import com.example.shuiyin.dto.ProcessRecordDto;
import com.example.shuiyin.service.FileService;
import com.example.shuiyin.service.MinioStorageService;
import com.example.shuiyin.service.ProcessRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.GetMapping;
import io.minio.GetObjectArgs;
import io.minio.GetObjectResponse;
import io.minio.MinioClient;
import com.example.shuiyin.config.MinioConfig;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import java.net.URLEncoder;
import com.example.shuiyin.entity.FileInfo;
import com.example.shuiyin.exception.AppException;

@RestController
@RequestMapping("/api/files")
@RequiredArgsConstructor
@Slf4j
public class FileController {

    private final FileService fileService;
    private final ProcessRecordService processRecordService;
    private final MinioStorageService minioStorageService;
    private final MinioClient minioClient;
    private final MinioConfig minioConfig;

    /**
     * 获取用户文件列表
     */
    @GetMapping
    public ResponseEntity<ApiResponse<Page<FileDto>>> getUserFiles(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int limit,
            @RequestAttribute("userId") Long userId) {
        log.info("用户[{}]获取文件列表, 页码: {}, 每页数量: {}", userId, page, limit);
        Page<FileDto> files = fileService.getUserFiles(userId, page, limit);
        return ResponseEntity.ok(ApiResponse.success("获取文件列表成功", files));
    }

    /**
     * 删除文件
     */
    @DeleteMapping("/{fileId}")
    public ResponseEntity<ApiResponse<String>> deleteFile(
            @PathVariable String fileId,
            @RequestAttribute("userId") Long userId) {
        
        log.info("删除文件: fileId={}, userId={}", fileId, userId);
        
        try {
            // 验证用户是否有权限删除文件
            fileService.verifyFileOwnership(fileId, userId);
            
            // 删除文件
            fileService.deleteFile(fileId, userId);
            
            return ResponseEntity.ok(ApiResponse.success("文件删除成功", ""));
        } catch (AppException e) {
            log.error("删除文件业务异常: {}", e.getMessage(), e);
            return ResponseEntity.status(e.getStatusCode())
                    .body(ApiResponse.error(e.getCode(), e.getMessage()));
        } catch (Exception e) {
            log.error("删除文件失败: {}", e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "删除文件失败: " + e.getMessage()));
        }
    }

    /**
     * 获取处理历史
     */
    @GetMapping("/history")
    public ResponseEntity<ApiResponse<Page<ProcessRecordDto>>> getProcessHistory(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int limit,
            @RequestAttribute("userId") Long userId) {
        log.info("用户[{}]获取处理历史, 页码: {}, 每页数量: {}", userId, page, limit);
        Page<ProcessRecordDto> history = processRecordService.getProcessHistory(userId, page, limit);
        return ResponseEntity.ok(ApiResponse.success("获取处理历史成功", history));
    }

    @GetMapping("/files/**")
    public ResponseEntity<Resource> getFile(HttpServletRequest request) {
        try {
            // 从请求路径中提取文件路径
            String requestPath = request.getRequestURI();
            String filePath = requestPath.substring("/files/".length());
            
            // 获取文件
            InputStream inputStream = minioStorageService.getObject(filePath);
            InputStreamResource resource = new InputStreamResource(inputStream);
            
            // 设置Content-Type
            String contentType = request.getServletContext().getMimeType(filePath);
            if (contentType == null) {
                contentType = "application/octet-stream";
            }
            
            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType(contentType))
                    .body(resource);
        } catch (Exception e) {
            log.error("获取文件失败: {}", e.getMessage(), e);
            return ResponseEntity.notFound().build();
        }
    }

    /**
     * 通过应用服务器代理访问Minio中的头像文件（改进版本）
     */
    @GetMapping("/avatar/{userId}/{filename:.+}")
    public void getAvatarFileImproved(
            @PathVariable Long userId,
            @PathVariable String filename,
            HttpServletResponse response) {
        
        String objectName = "avatars/" + userId + "/" + filename;
        log.info("请求访问头像文件: {}", objectName);
        
        try {
            // 从MinIO获取文件
            GetObjectResponse object = minioClient.getObject(
                GetObjectArgs.builder()
                    .bucket(minioConfig.getBucket())
                    .object(objectName)
                    .build()
            );
            
            // 设置响应头
            String contentType = object.headers().get("Content-Type");
            if (contentType == null) {
                contentType = "image/jpeg"; // 默认头像类型
            }
            response.setContentType(contentType);
            
            // 设置缓存控制
            response.setHeader("Cache-Control", "max-age=86400"); // 缓存1天
            
            // 复制文件内容到响应输出流
            try (InputStream is = object) {
                IOUtils.copy(is, response.getOutputStream());
                response.flushBuffer();
            }
        } catch (Exception e) {
            log.error("获取头像文件失败: {}", e.getMessage(), e);
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            try {
                response.getWriter().write("头像不存在或无法访问");
            } catch (IOException ex) {
                log.error("写入响应失败", ex);
            }
        }
    }

    @GetMapping("/download/{fileId}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String fileId, HttpServletRequest request) {
        try {
            // 获取文件信息
            FileInfo fileInfo = fileService.getFileInfo(fileId);
            
            // 加载文件资源
            Resource resource = minioStorageService.loadFileAsResource(fileInfo.getFilePath());
            
            // 确定内容类型
            String contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
            if (contentType == null) {
                contentType = "application/octet-stream";
            }
            
            // 设置文件名，支持中文
            String fileName = fileInfo.getFileName();
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
            
            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType(contentType))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"")
                    .body(resource);
        } catch (Exception e) {
            log.error("下载文件失败: {}", e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
} 